﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Transactions;
using System.Windows;
using System.Windows.Documents;
using AtlantisClientWPF.APIS;
using AtlantisClientWPF.Bins;
using AtlantisClientWPF.ServiceReference1;
using Dal;
using LoveMusic.Helpers;

namespace AtlantisClientWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Private

        private delegate void TickerDelegate(string s);
        TickerDelegate tickerDelegate1;
        TickerDelegate tickerDelegate2;
        TickerDelegate tickerDelegate3;
        TickerDelegate tickerDelegate4;
        TickerDelegate tickerDelegateTakenIDs;
        TickerDelegate tickerDelegateException;
        TickerDelegate tickerDelegateBillBoard;

        static volatile int krug = 0;
        int skip = -10;
        private const int threadNumber = 1;
        Thread[] ths = new Thread[8];

        #endregion

        public MainWindow()
        {
            InitializeComponent();
            tickerDelegate1 = new TickerDelegate(SetThread1Ticker);
            tickerDelegate2 = new TickerDelegate(SetThread2Ticker);
            tickerDelegate3 = new TickerDelegate(SetThread3Ticker);
            tickerDelegate4 = new TickerDelegate(SetThread4Ticker);
            tickerDelegateTakenIDs = new TickerDelegate(SetTakenIDTicker);
            tickerDelegateException = new TickerDelegate(SetTickerDelegateException);
            tickerDelegateBillBoard = new TickerDelegate(SetTickerDelegateBillBoard);
        }


        #region Atlantis

        private static int currentCount = 0;
        private static WorkState _State = new WorkState();
        static Semaphore s = new Semaphore(1, 1);  // Available=1; Capacity=1
        static readonly object _locker = new object();
        Mp3FileApi mp3FileApi = new Mp3FileApi();
        static YouTubeApi youTube = new YouTubeApi();

        private void UpdateSongs()
        {
            int threadSkip = 10;
            AtlantisClient client;

            int thisThreadNumber = currentCount++;

            if (thisThreadNumber == 0)
                threadSkip = 0;
            else
            {
                Thread.Sleep(thisThreadNumber * 1000);
                threadSkip = thisThreadNumber * threadSkip;
            }

            #region private

            List<string> mp3List;

            string encodingCode = string.Empty;
            string videoID = string.Empty;
            string tags = string.Empty;
            string youTubeDescrption = string.Empty;
            bool nekojUslov = true;
            List<Story> allSongs;

            #endregion

            string tekstce = "Connecting to server...";
            ShowMessage(Thread.CurrentThread.Name + "|" + tekstce, thisThreadNumber);

            while (nekojUslov)
            {
                // Initialize
                Dal.Wrapper wrapper = new Dal.Wrapper();
                wrapper.songs = new List<Story>();
                wrapper.takenIDs = new List<int>();
                wrapper.removeIDs = new List<int>();

                // Get the ids from static object
                wrapper.takenIDs = _State.GetTakenIDs();

                client = new AtlantisClient();
                try
                {
                    lock (_locker)
                    {
                        ShowMessage(Thread.CurrentThread.Name + "|" + "Getting Songs from server...", thisThreadNumber);
                        wrapper = client.GetStories("nekojalozinka", skip, 10, wrapper);
                    }
                }
                catch (Exception e)
                {
                    client.Abort();
                    ShowMessage(e.Message.ToString(), 6);
                }
                finally
                {
                    client.Close();
                }

                allSongs = wrapper.songs;

                // update the static object with new IDs
                _State.UpdateTakenIDs(wrapper.takenIDs);

                ShowTakenIDs(_State.GetTakenIDs());

                if (allSongs.Count() <= 0)
                {
                    nekojUslov = false;
                    ShowMessage("No Songs, that means probably Atlantis client in faulty state.", thisThreadNumber);
                    break;
                }
                else
                {

                    foreach (var story in allSongs)
                    {
                        story.SetAsChangeTrackingRoot(true);

                        ShowMessage("Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug++, thisThreadNumber);
                        story.Title = WebHelper.RemoveSpecialCharacters(story.Title);

                        #region YouTube Video

                        youTube.GetYouTubeVideo(story.Title, story.ArtistName, ref encodingCode, ref videoID, ref tags, ref youTubeDescrption);

                        if (youTubeDescrption != string.Empty)
                            story.youTubeDescription = youTubeDescrption;
                        story.YouTubeID = videoID;
                        if (tags != null && tags != string.Empty)
                        {
                            story.inputTags = WebHelper.RemoveSpecialCharactersExceptComma(tags);
                            story.inputTags = WebHelper.RemoveDuplicates(tags);

                        }

                        #endregion

                        #region Tags

                        //                        if (!string.IsNullOrEmpty(story.inputTags))
                        //                        {
                        //                            var tagsArray = story.inputTags.Split(',');
                        //                            List<Tag> tempListTags = new List<Tag>();
                        //                            for (var i = 0; i < tagsArray.Length; i++)
                        //                            {
                        //                                if (tagsArray[i].Length > 0)
                        //                                {
                        //                                    if (tagsArray[i].Length > 64)
                        //                                        tagsArray[i] = tagsArray[i].Substring(0, 64);

                        //                                    tempListTags.Add(new Tag()
                        //                                    {
                        //                                        Name = tagsArray[i].Trim(),
                        //                                        status = 0
                        //                                    });
                        //                                }
                        //                            }

                        //                            s.WaitOne(); // Semaphore only one at a time 

                        //                            client = new AtlantisClient();

                        //                            try
                        //                            {
                        //                                tempListTags = client.GetTagStatus(tempListTags.ToArray()).ToList();
                        //                            }
                        //                            catch (Exception e)
                        //                            {
                        //                                client.Abort();
                        //                                ShowMessage(e.ToString(), 6);
                        //                                s.Release();
                        //#if DEBUG
                        //                                throw e;
                        //#else
                        //                                    continue;
                        //#endif
                        //                            }
                        //                            finally
                        //                            {
                        //                                client.Close();

                        //                            }

                        //                            s.Release();

                        //                            if (tempListTags.Count > 0)
                        //                            {
                        //                                var newTags = new List<Tag>();
                        //                                var oldTags = new List<Tag>();

                        //                                for (var i = 0; i < tempListTags.Count; i++)
                        //                                {
                        //                                    if (tempListTags[i].status == 0)
                        //                                        oldTags.Add(tempListTags[i]);
                        //                                    else
                        //                                        newTags.Add(tempListTags[i]);

                        //                                }

                        //                                s.WaitOne();
                        //                                if (newTags.Count > 0)
                        //                                {
                        //                                    client = new AtlantisClient();
                        //                                    try
                        //                                    {
                        //                                        newTags = client.InsertTags(newTags.ToArray()).ToList();
                        //                                    }
                        //                                    catch (Exception e)
                        //                                    {
                        //                                        client.Abort();
                        //                                        ShowMessage(e.ToString(), 6);
                        //                                        s.Release();
                        //#if DEBUG
                        //                                        throw e;
                        //#else
                        //                                            continue;
                        //#endif
                        //                                    }
                        //                                    finally
                        //                                    {
                        //                                        client.Close();

                        //                                    }

                        //                                    foreach (var newTaggy in newTags)
                        //                                    {
                        //                                        story.StoryTags.Add(new StoryTag { StoryID = story.ID, TagID = newTaggy.ID });
                        //                                    }
                        //                                }
                        //                                s.Release();

                        //                                if (oldTags.Count > 0)
                        //                                {
                        //                                    for (var i = 0; i < oldTags.Count; i++)
                        //                                    {
                        //                                        if (oldTags[i].ID == 0)
                        //                                            throw new ApplicationException("BAAAAD");
                        //                                        story.StoryTags.Add(new StoryTag { StoryID = story.ID, TagID = oldTags[i].ID });
                        //                                    }
                        //                                }
                        //                            }
                        //                        }



                        #endregion Tags

                        #region mp3Files

                        ShowMessage(Thread.CurrentThread.Name + "|" + "Getting mp3 songs for Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug, thisThreadNumber);

                        lock (_locker)
                        {
                            mp3List = mp3FileApi.GetMp3Urls(story.ArtistName, story.Title);
                        }

                        ShowMessage(Thread.CurrentThread.Name + "|" + "Finished Getting mp3 songs for Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug, thisThreadNumber);
                        int counterMp3 = 1;

                        foreach (string mp3Url in mp3List)
                        {
                            if (mp3Url.Length < 512)
                            {
                                MP3FILE mp3File = new MP3FILE()
                                {
                                    Story_ID = story.ID,
                                    url = mp3Url,
                                    IsValid = true,
                                    Title = WebHelper.CutString(WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.Title)) + " - " + WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.ArtistName)), 127),
                                    DateCreated = DateTime.Now,
                                    Count = counterMp3
                                };
                                counterMp3++;
                                // Add the mp3 to story
                                story.MP3FILEs.Add(mp3File);
                            }
                        }

                        #endregion

                        #region Votes

                        story.PublishedOn = new DateTime(2006, 4, 7, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);

                        #endregion Votes

                        story.Status = 1;
                    }

                    wrapper.songs = allSongs;

                    client = new AtlantisClient();
                    try
                    {
                        lock (_locker)
                        {
                            ShowMessage(Thread.CurrentThread.Name + "|" + ". Trying to update database", thisThreadNumber);
                            wrapper = client.UpdateStories("nekojalozinka", wrapper);
                        }
                    }
                    catch (System.ServiceModel.CommunicationObjectFaultedException e)
                    {
                        client.Abort();
                        ShowMessage(Thread.CurrentThread.Name + "|" + e.Message, 6);
                    }
                    catch (Exception e)
                    {
                        client.Abort();
                        ShowMessage(Thread.CurrentThread.Name + "|" + e.Message, 6);
                    }
                    finally
                    {
                        client.Close();
                    }

                    // take the new id's with the removed IDs
                    if (wrapper.removeIDs.Count > 0)
                        _State.RemoveTakenIDs(wrapper.removeIDs);
                    else if (wrapper.takenIDs.Count > 0)
                        _State.RemoveTakenIDs(wrapper.takenIDs);

                    ShowTakenIDs(_State.GetTakenIDs());
                    ShowMessage(Thread.CurrentThread.Name + "|" + ". Done Updating", thisThreadNumber);
                }
            }
            ShowMessage("Thread finishing?!!! KRUG=" + krug, thisThreadNumber);
        }

        private void UpdateSongs2()
        {
            #region private

            List<string> mp3List;

            string encodingCode = string.Empty;
            string videoID = string.Empty;
            string tags = string.Empty;
            string youTubeDescrption = string.Empty;
            bool nekojUslov = true;
            List<Story> allSongs;
            Stopwatch stopWatchFullTime = new Stopwatch();
            int threadSkip = 10;
            int thisThreadNumber = currentCount++;
            int numberOfAttempts = 0;

            #endregion

            if (thisThreadNumber == 0)
                threadSkip = 0;
            else
            {
                Thread.Sleep(thisThreadNumber * 1000);
                threadSkip = thisThreadNumber * threadSkip;
            }

            string tekstce = "Connecting to server...";
            stopWatchFullTime.Start();
            ShowMessage(Thread.CurrentThread.Name + "|" + tekstce, thisThreadNumber);

            while (nekojUslov)
            {
                // Initialize

                Dal.Wrapper wrapper = new Dal.Wrapper();
                wrapper.songs = new List<Story>();
                wrapper.takenIDs = new List<int>();
                wrapper.removeIDs = new List<int>();

                // Get the ids from static object
                wrapper.takenIDs = _State.GetTakenIDs();

                try
                {
                    lock (_locker)
                    {
                        ShowMessage(Thread.CurrentThread.Name + "|" + "Getting Songs from server... Attempts=" + numberOfAttempts, thisThreadNumber);
                        wrapper = GetStories(20, 40);
                    }
                }
                catch (Exception e)
                {
                    ShowMessage(e.Message.ToString(), 6);
                }

                allSongs = wrapper.songs;

                // update the static object with new IDs
                _State.UpdateTakenIDs(wrapper.takenIDs);

                ShowTakenIDs(_State.GetTakenIDs());

                if (allSongs.Count() > 0)
                {
                    foreach (var story in allSongs)
                    {
                        krug++;
                        story.Title = WebHelper.RemoveSpecialCharacters(story.Title);

                        #region YouTube Video

                        youTube.GetYouTubeVideo(story.Title, story.ArtistName, ref encodingCode, ref videoID, ref tags, ref youTubeDescrption);

                        if (youTubeDescrption != string.Empty)
                            story.youTubeDescription = youTubeDescrption;
                        story.YouTubeID = videoID;
                        if (tags != null && tags != string.Empty)
                        {
                            story.inputTags = WebHelper.RemoveSpecialCharactersExceptComma(tags);
                            story.inputTags = WebHelper.RemoveDuplicates(tags);

                        }

                        #endregion

                        #region mp3Files

                        // ShowMessage(Thread.CurrentThread.Name + "|" + "Getting mp3 songs for Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug, thisThreadNumber);
                        Stopwatch stopWatch = new Stopwatch(); //creating object of Stopwatch class
                        stopWatch.Start(); //starting the stopwatch

                        //lock (_locker)
                        mp3List = mp3FileApi.GetMp3Urls(story.ArtistName, story.Title);

                        stopWatch.Stop();

                        ShowMessage(Thread.CurrentThread.Name + "|" + " Time=" + stopWatch.Elapsed + " | Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug, thisThreadNumber);
                        int counterMp3 = 1;

                        story.mp3FilesList = new List<MP3FILE>();

                        foreach (string mp3Url in mp3List)
                        {
                            if (mp3Url.Length < 512)
                            {
                                MP3FILE mp3File = new MP3FILE()
                                {
                                    Story_ID = story.ID,
                                    url = mp3Url,
                                    IsValid = true,
                                    Title = WebHelper.CutString(WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.Title)) + " - " + WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.ArtistName)), 127),
                                    DateCreated = DateTime.Now,
                                    Count = counterMp3
                                };

                                // Add the mp3 to story
                                story.mp3FilesList.Add(mp3File);

                                counterMp3++;
                            }
                        }

                        #endregion

                        #region Votes

                        story.PublishedOn = new DateTime(2006, 4, 7, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);

                        #endregion Votes

                        story.Status = 1;
                    }

                    wrapper.songs = allSongs;

                    lock (_locker)
                    {
                        ShowMessage(Thread.CurrentThread.Name + "|" + ". Trying to update database Attempts=" + numberOfAttempts, thisThreadNumber);
                        wrapper = UpdateStories(wrapper);

                        if (wrapper.errorDetails != null)
                            ShowMessage(Thread.CurrentThread.Name + "|" + wrapper.errorDetails.Message, 6);
                    }



                    // take the new id's with the removed IDs
                    //if (wrapper.removeIDs.Count > 0)
                    //    _State.RemoveTakenIDs(wrapper.removeIDs);
                    //else 
                    if (wrapper.takenIDs.Count > 0)
                        _State.RemoveTakenIDs(wrapper.takenIDs);

                    ShowTakenIDs(_State.GetTakenIDs());
                    ShowMessage(Thread.CurrentThread.Name + "|" + ". Done Updating Attempts=" + numberOfAttempts, thisThreadNumber);
                }
                else
                    numberOfAttempts++;
            }

            stopWatchFullTime.Stop();
            ShowMessage("Thread finishing?!!! KRUG=" + krug + "| Time=" + stopWatchFullTime.Elapsed, thisThreadNumber);
        }

        #endregion

        #region Helper methods

        /// <summary>
        /// Add elements to the list only if they aren't already there
        /// </summary>
        /// <param name="mainList"></param>
        /// <param name="addList"></param>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        protected int[] AddElements(int[] mainList, int[] addList)
        {
            for (int i = 0; i < addList.Length; i++)
            {
                if (!mainList.Contains(addList[i]))
                    mainList[mainList.Length + 1] = addList[i];
            }
            return mainList;
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        protected List<int> AddElements(List<int> mainList, List<int> addList)
        {
            //mainList= AddElements(mainList.ToArray(),addList.ToArray()).ToList();
            //List<int> tempList= new List<int>();

            for (int i = 0; i < addList.Count; i++)
            {
                if (!mainList.Contains(addList[i]))
                {
                    mainList.Add(addList[i]);
                }
            }

            //foreach (int item in addList)
            //{
            //    if (!mainList.Contains(item))
            //    {
            //        tempList.Add(item);

            //    }
            //}

            //foreach (int item in tempList)
            //{
            //    mainList.Add(item);
            //}

            return mainList;
        }

        /// <summary>
        /// Displays status message for thread 1.
        /// </summary>
        /// <param name="tekstce"></param>
        /// <param name="threadNumber"></param>
        private void ShowMessage(string tekstce, int threadNumber)
        {
            switch (threadNumber)
            {
                case 0:
                    Dispatcher.Invoke(tickerDelegate1, new object[] { threadNumber.ToString() + ". " + tekstce });
                    break;
                case 1:
                    Dispatcher.Invoke(tickerDelegate2, new object[] { threadNumber.ToString() + ". " + tekstce });
                    break;
                case 2:
                    Dispatcher.Invoke(tickerDelegate3, new object[] { threadNumber.ToString() + ". " + tekstce });
                    break;
                case 3:
                    Dispatcher.Invoke(tickerDelegate4, new object[] { threadNumber.ToString() + ". " + tekstce });
                    break;
                case 6:
                    Dispatcher.Invoke(tickerDelegateException, new object[] { threadNumber.ToString() + ". " + tekstce });
                    break;
                case 77:
                    Dispatcher.Invoke(tickerDelegateBillBoard, new object[] { threadNumber.ToString() + ". " + tekstce });
                    break;
                default: break;
            }
        }

        /// <summary>
        /// Helper method that shows taken ids in label.
        /// </summary>
        /// <param name="takenIDs"></param>
        private void ShowTakenIDs(List<int> takenIDs)
        {
            string strTakenIDs = string.Empty;
            strTakenIDs = "Total Elements=" + takenIDs.Count;
            foreach (int item in takenIDs)
            {
                strTakenIDs = strTakenIDs + "\n" + item.ToString();
            }
            strTakenIDs = strTakenIDs + "\n";

            Dispatcher.Invoke(tickerDelegateTakenIDs, new object[] { threadNumber.ToString() + ". " + strTakenIDs });
        }

        private void SetTakenIDTicker(string strTakenIDs)
        {
            lblTakeIDs.Content = strTakenIDs;
        }

        private void SetTickerDelegateException(string strException)
        {
            lblException.Content = strException;
        }

        private void SetTickerDelegateBillBoard(string strTekst)
        {
            lblBillBoard.Content = strTekst;
        }

        private void SetThread1Ticker(string s)
        {
            lblMainStatus.Content = s;
        }

        private void SetThread2Ticker(string s)
        {
            lblSecondStatus.Content = s;
        }

        private void SetThread3Ticker(string s)
        {
            lbl3Thread.Content = s;
        }

        private void SetThread4Ticker(string s)
        {
            lbl4Thread.Content = s;
        }

        #endregion

        #region Event Clicks

        private void btnNewUpdate_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < threadNumber; i++)
            {
                ths[i] = new Thread(new ThreadStart(UpdateSongs2));
                ths[i].Name = "Thread No:" + i;
                ths[i].IsBackground = true;
                ths[i].Start();
            }
            btnNewUpdate.IsEnabled = false;
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < threadNumber; i++)
            {
                ths[i] = new Thread(new ThreadStart(UpdateSongs));
                ths[i].Name = "Thread No:" + i;
                ths[i].IsBackground = true;
                ths[i].Start();
            }
            btnStart.IsEnabled = false;
        }

        private void btnBillBoard_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 1; i++)
            {
                ths[i] = new Thread(new ThreadStart(BillyWork));
                ths[i].IsBackground = true;
                ths[i].Start();
            }
            btnBillBoard.IsEnabled = false;
        }

        private void btnLastFM_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 1; i++)
            {
                ths[i] = new Thread(new ThreadStart(InsertSongsFromLastFm));
                ths[i].IsBackground = true;
                ths[i].Start();
            }
            btnLastFM.IsEnabled = false;

        }

        #endregion

        #region BillBoard

        private void BillyWork()
        {
            // SubmitBotBillBoard("I'm Back", 2, "Latest best songs", "TI");

            BillboardAPI billy = new BillboardAPI();

            ShowMessage("Getting songs!", 77);
            List<SongBinz> songs = billy.GetSongzzz();

            #region Find out the category

            foreach (SongBinz billBoardBin in songs)
            {
                ShowMessage("Adding song songName=" + billBoardBin.SongName, 77);
                if (billBoardBin.Category == 0)
                {
                    AllMusicBin allMusicBin = AllMusicAPI.SearchRequest(billBoardBin.ArtistName);
                    if (allMusicBin != null)
                        billBoardBin.Category = allMusicBin.Category;
                    else
                        billBoardBin.Category = 15;
                    billBoardBin.Description = "Fresh";
                }
            }

            #endregion

            try
            {
                int status = SubmitBotBillBoard(songs);
                //billBoardBin.SongName, billBoardBin.Category, "Latest best songs", billBoardBin.ArtistName);
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString(), 6);
            }
        }

       
        private int SubmitBotBillBoard(List<SongBinz> songs)
        {
            List<Story> stories = new List<Story>();
            List<string> mp3List= new List<string>();
            string encodingCode = string.Empty;
            string tags = string.Empty;
            string videoID = string.Empty;
            string imageURL = string.Empty;
            string youTubeDescrption = string.Empty;
            int artistID;
            string artistName = string.Empty;
            Mp3FileApi mp3FileApi = new Mp3FileApi();
            YouTubeApi youTube = new YouTubeApi();

            foreach(SongBinz sBinz in songs)
            {
                #region  Create artist if it doesn't exist
                artistName = sBinz.ArtistName.Replace(".", "");
                using (ModelDataContext db = new ModelDataContext())
                {
                    ARTIST art = db.GetArtistByName(artistName);
                    if (art != null)
                        artistID = art.ARTIST_IDZ;
                    else
                        artistID = db.CreateArtist(artistName, sBinz.Category);
                }

                #endregion 
                
                Story song = new Story
                     {
                             Title = sBinz.SongName,
                             PostedByUserName = "Atlantis",
                             PublishedOn = null,
                             PostedOn = DateTime.Now,
                             Playcount = 20000,
                             Listeners = 20000,
                             ArtistName = sBinz.ArtistName,
                             Description = "This is one of many songs from " + sBinz.ArtistName.Trim(),
                             youTubeDescription = "This is one of many songs from " + sBinz.ArtistName.Trim(),
                             ARTIST_IDZ = artistID,
                             CategoryID = sBinz.Category,
                             Status=0
                     };

                      #region Votes

                      Vote vote = new Vote { StoryID = song.ID, UserID = new Guid("86A13EB9-9CFB-414C-9C12-A580934E86E6"), Timestamp = song.PostedOn };
                      song.Votes.Add(vote);
                          

                      #endregion Votes
                      
                      stories.Add(song);
            }
            ShowMessage("Inserting songs...", 77);

            stories = InsertSongs(stories);


            Dal.Wrapper wrapper = new Dal.Wrapper();
                wrapper.songs = stories;
                wrapper.takenIDs = new List<int>();
                wrapper.removeIDs = new List<int>();

                // Get the ids from static object
                wrapper.takenIDs = _State.GetTakenIDs();

                // update the static object with new IDs
                _State.UpdateTakenIDs(wrapper.takenIDs);

                ShowTakenIDs(_State.GetTakenIDs());
               
                if (wrapper.songs.Count() > 0)
                {
                    foreach (var story in wrapper.songs)
                    {
                        krug++;
                        story.Title = WebHelper.RemoveSpecialCharacters(story.Title);

                        #region YouTube Video

                        youTube.GetYouTubeVideo(story.Title, story.ArtistName, ref encodingCode, ref videoID, ref tags, ref youTubeDescrption);

                        if (youTubeDescrption != string.Empty)
                            story.youTubeDescription = youTubeDescrption;
                        story.YouTubeID = videoID;
                        if (tags != null && tags != string.Empty)
                        {
                            story.inputTags = WebHelper.RemoveSpecialCharactersExceptComma(tags);
                            story.inputTags = WebHelper.RemoveDuplicates(tags);
                        }

                        #endregion

                        #region mp3Files

                        // ShowMessage(Thread.CurrentThread.Name + "|" + "Getting mp3 songs for Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug, thisThreadNumber);
                        Stopwatch stopWatch = new Stopwatch(); //creating object of Stopwatch class
                        stopWatch.Start(); //starting the stopwatch

                        //lock (_locker)
                        mp3List = mp3FileApi.GetMp3Urls(story.ArtistName, story.Title);

                        stopWatch.Stop();
                        ShowMessage(Thread.CurrentThread.Name + "|" + " Time=" + stopWatch.Elapsed + " | Song Name=" + story.Title + " Artist=" + story.ArtistName + " Krug=" + krug, 2);


                        int counterMp3 = 1;

                        story.mp3FilesList = new List<MP3FILE>();

                        foreach (string mp3Url in mp3List)
                        {
                            if (mp3Url.Length < 512)
                            {
                                MP3FILE mp3File = new MP3FILE()
                                {
                                    Story_ID = story.ID,
                                    url = mp3Url,
                                    IsValid = true,
                                    Title = WebHelper.CutString(WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.Title)) + " - " + WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.ArtistName)), 127),
                                    DateCreated = DateTime.Now,
                                    Count = counterMp3
                                };

                                // Add the mp3 to story
                                story.mp3FilesList.Add(mp3File);

                                counterMp3++;
                            }
                        }

                        #endregion

                        #region Votes

                        story.PublishedOn = new DateTime(2006, 4, 7, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);

                        #endregion Votes

                        story.Status = 100; // Billboard status
                    }

                    //wrapper.songs = allSongs;

                    lock (_locker)
                    {
                        ShowMessage("Updating songs!", 77);
                        wrapper = UpdateStories(wrapper);

                        if (wrapper.errorDetails != null)
                            ShowMessage(Thread.CurrentThread.Name + "|" + wrapper.errorDetails.Message, 6);
                    }
           }
           
            return 0;
        }



        #endregion

        #region New Music Engine Submiter of 10 songs with ratings

        /// <summary>
        /// Zemi 10 artisti
        /// zemi gi pesnite od last fm, so rating
        /// insertuvaj gi vo baza preku web servicot 
        /// Aj da pocneme so eden thread samo znaci bez tredovi
        /// </summary>

        public void InsertSongsFromLastFm()
        {
            AtlantisClient client;
            List<ARTIST> artists = new List<ARTIST>();
            string tekstce = "Connecting to server...";
            ShowMessage(tekstce, 1);

            while (true)
            {
                client = new AtlantisClient();
                ShowMessage("Getting artists from server...", 1);

                s.WaitOne();
                try
                {
                    artists = client.GetArtists("nekojalozinka", 10, 0).ToList();
                }
                catch (Exception e)
                {
                    client.Abort();
                    ShowMessage(e.ToString(), 6);
                    s.Release();
#if DEBUG
                    continue;
#else   
                 continue;
#endif
                }
                finally
                {
                    client.Close();
                }
                s.Release();

                if (artists.Count == 0)
                    break;
                // url http://ws.audioscrobbler.com/2.0/?method=artist.gettoptracks&artist=cher&api_key=b25b959554ed76058ac220b7b2e0a026

                LastFmAPI lastFmAPI = new LastFmAPI();
                foreach (ARTIST artist in artists)
                {
                    ShowMessage("Getting songs for artist=" + artist.NAME, 1);
                    var songs = lastFmAPI.GetSongs(artist);

                    client = new AtlantisClient();
                    try
                    {
                        if (songs.Count != 0)
                        {
                            ShowMessage("Trying to update songs count=" + songs.Count + "| Artist =" + artist.NAME, 1);
                            Thread.Sleep(7);
                            int status = client.SubmitBotLastFM("nekojalozinka", songs.ToArray());
                            ShowMessage("Success. Artist=" + artist.NAME + " Status=" + status, 1);
                        }
                        else
                        {
                            // stavi mu status 70 ako bidnala nekoja greska. 
                            artist.status = 70;
                            client.SetArtistSongless("nekojalozinka", artist);
                            ShowMessage("Artist =" + artist.NAME + " is songless", 1);
                        }
                    }
                    catch (Exception ex)
                    {
                        client.Abort();
                        ShowMessage(ex.ToString(), 6);
                        continue;
                    }
                    finally
                    {
                        client.Close();
                    }
                }
            }
        }

        /// <summary>
        /// Ultimate metthod get artist and song information from last fm and mp3 and youtube and insert all
        /// at once. 
        /// </summary>
        public void InsertSongs()
        {
            AtlantisClient client;
            List<ARTIST> artists = new List<ARTIST>();
            string tekstce = "Connecting to server...";
            ShowMessage(tekstce, 1);

            while (true)
            {
                client = new AtlantisClient();
                ShowMessage("Getting artists from server...", 1);

                s.WaitOne();
                try
                {
                    artists = client.GetArtists("nekojalozinka", 10, 0).ToList();
                }
                catch (Exception e)
                {
                    client.Abort();
                    ShowMessage(e.ToString(), 6);
                    s.Release();
#if DEBUG
                    continue;
#else   
                 continue;
#endif
                }
                finally
                {
                    client.Close();
                }
                s.Release();

                if (artists.Count == 0)
                    break;
                // url http://ws.audioscrobbler.com/2.0/?method=artist.gettoptracks&artist=cher&api_key=b25b959554ed76058ac220b7b2e0a026

                LastFmAPI lastFmAPI = new LastFmAPI();
                foreach (ARTIST artist in artists)
                {
                    ShowMessage("Getting songs for artist=" + artist.NAME, 1);
                    var songs = lastFmAPI.GetSongs(artist);

                    client = new AtlantisClient();
                    try
                    {
                        if (songs.Count != 0)
                        {
                            ShowMessage("Trying to update songs count=" + songs.Count + "| Artist =" + artist.NAME, 1);
                            Thread.Sleep(7);
                            int status = client.SubmitBotLastFM("nekojalozinka", songs.ToArray());
                            ShowMessage("Success. Artist=" + artist.NAME + " Status=" + status, 1);
                        }
                        else
                        {
                            artist.status = 70;
                            client.SetArtistSongless("nekojalozinka", artist);
                            ShowMessage("Artist =" + artist.NAME + " is songless", 1);
                        }
                    }
                    catch (Exception ex)
                    {
                        client.Abort();
                        ShowMessage(ex.ToString(), 6);
                        continue;
                    }
                    finally
                    {
                        client.Close();
                    }
                }
            }
        }
        #endregion

        #region Dal Methods

        // Get songs only for skip 1 thread only.
        public Wrapper GetStories(int skip, int take)
        {
            Wrapper wrapper = new Wrapper();
            List<StoryHolder> songs;
            int brojac = 0;
            int numberOfSongs = 20;
            try
            {
                using (ModelDataContext db = new ModelDataContext())
                {
                    db.CommandTimeout = 180;
                    songs = db.Stories.
                                        Where(s => s.Status == 0)
                                        .Select(s => new StoryHolder
                                        {
                                            ID = s.ID,
                                            Title = s.Title,
                                            ArtistName = s.ArtistName
                                        })
                                        .Take(take)
                                        .ToList();
                }

                wrapper.takenIDs = new List<int>();
                wrapper.removeIDs = new List<int>();
                wrapper.songs = new List<Story>();
                int counterOfSongs = 0;

                foreach (StoryHolder song in songs)
                {
                    if (brojac++ >= skip) // skip the first rows definied in skip this is faster done here than sql
                    {
                        wrapper.songs.Add(new Story { ID = song.ID, Title = song.Title, ArtistName = song.ArtistName });
                        wrapper.takenIDs.Add(song.ID);
                        if (counterOfSongs == numberOfSongs)
                            break;
                        counterOfSongs++;
                    }
                }

            }
            catch (Exception e)
            {
                wrapper.errorDetails = e;
            }

            return wrapper;
        }

        public Wrapper GetStories(int skip, int take, Wrapper wrapper)
        {
            try
            {
                List<int> listTakenIDs = wrapper.takenIDs;
                List<StoryHolder> songs;

                using (ModelDataContext db = new ModelDataContext())
                {
                    db.CommandTimeout = 60;
                    songs = db.Stories.
                                        Where(s => s.Status == 0 && !listTakenIDs.Contains(s.ID))
                                        .Select(s => new StoryHolder
                                        {
                                            ID = s.ID,
                                            Title = s.Title,
                                            ArtistName = s.ArtistName
                                        })
                                        .Take(take)
                                        .ToList();
                }

                // Add only the latest id's
                wrapper.takenIDs = new List<int>();
                foreach (StoryHolder song in songs)
                {
                    wrapper.songs.Add(new Story { ID = song.ID, Title = song.Title, ArtistName = song.ArtistName });
                    wrapper.takenIDs.Add(song.ID);
                }

                wrapper.songHolder = songs;
            }
            catch (Exception e)
            {
                wrapper.errorDetails = e;
            }

            return wrapper;
        }

        public Wrapper UpdateStories(Wrapper wrapper)
        {
            Debug.Assert(wrapper.songs != null);

            try
            {
                using (ModelDataContext db = new ModelDataContext())
                {
                    using (var ts = new TransactionScope())
                    {
                        foreach (Story story in wrapper.songs)
                        {
                            wrapper.removeIDs.Add(story.ID);
                            string songTitle = WebHelper.CutString(WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.Title)) + " - " + WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.ArtistName)), 127);

                            #region Mp3Files

                            string listMp3 = string.Empty;
                            foreach (MP3FILE mp3 in story.mp3FilesList)
                            {
                                listMp3 = listMp3 + mp3.url + ",";
                            }

                            listMp3.TrimEnd(',');

                            #endregion

                            db.spInsertStoryTagsMp3(story.inputTags, story.ID, listMp3, songTitle, story.YouTubeID, story.youTubeDescription, story.Status);
                        }

                        db.SubmitChanges();
                        ts.Complete();
                    }
                }
            }
            catch (Exception e)
            {
                wrapper.errorDetails = e;
            }

            return wrapper;
        }

        public Wrapper CreateUpdateStories(Wrapper wrapper)
        {
            Debug.Assert(wrapper.songs != null);

            try
            {
                using (ModelDataContext db = new ModelDataContext())
                {
                    using (var ts = new TransactionScope())
                    {
                        foreach (Story story in wrapper.songs)
                        {

                            wrapper.removeIDs.Add(story.ID);

                            // songTitle is for the mp3 files
                            // to do: Get the real file name of the mp3 and check it with the title if it is not a match don't add it.
                            string songTitle = WebHelper.CutString(WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.Title)) + " - " + WebHelper.CreateAmper(WebHelper.RemoveSpecialCharacters(story.ArtistName)), 127);

                            #region Mp3Files

                            string listMp3 = string.Empty;
                            foreach (MP3FILE mp3 in story.mp3FilesList)
                            {
                                listMp3 = listMp3 + mp3.url + ",";
                            }

                            listMp3.TrimEnd(',');

                            #endregion

                            db.spInsertStoryTagsMp3(story.inputTags, story.ID, listMp3, songTitle, story.YouTubeID, story.youTubeDescription, story.Status);
                        }

                        db.SubmitChanges();
                        ts.Complete();
                    }
                }
            }
            catch (Exception e)
            {
                wrapper.errorDetails = e;
            }

            return wrapper;
        }

        public int SubmitBotBillBoard(string songName, int category, string description, string artistName)
        {
            string encodingCode = string.Empty;
            string tags = string.Empty;
            string videoID = string.Empty;
            string imageURL = string.Empty;
            string youTubeDescrption = string.Empty;
            //songTitle = WebHelper.RemoveSpecialCharacters(songTitle);
            artistName = WebHelper.RemoveSpecialCharactersExceptTire(artistName);
            Mp3FileApi mp3FileApi = new Mp3FileApi();
            List<string> lstMp3Songs = mp3FileApi.GetMp3Urls(artistName, songName);
            YouTubeApi youTube = new YouTubeApi();
            youTube.GetYouTubeVideo(songName, artistName, ref encodingCode, ref videoID, ref tags, ref youTubeDescrption);

            using (ModelDataContext db = new ModelDataContext())
            {
                if (artistName != "TI")
                    if (!db.StoryExists(songName, artistName))
                    {
                        db.SubmitStoryBot(songName, artistName, category, description, tags, lstMp3Songs, videoID, new Guid("1685CC87-BA2F-450B-BBE6-2F81A0F149A9"), youTubeDescrption);
                    }
            }

            return 0;
        }

        public List<Story> InsertSongs(List<Story> stories)
        {
            try
            {
                using (ModelDataContext db = new ModelDataContext())
                {
                    foreach (Story story in stories)
                    {
                        db.Stories.InsertOnSubmit(story);
                    }
                    db.SubmitChanges();
                }
                return stories;
            }
            catch(Exception ex)
            {// fail
                ShowMessage("Ekseption on InsertSongs()=" + ex, 77);
                return null;
            }
        }

        #endregion

    }
}
